#!D:/Program Files/Python37/python
# -*- coding: utf-8 -*-
# @Time : 2020/7/8 18:46
# @Author : Xingzhi Zhao
# @File : RED.py
# @Software : PyCharm
import sys, os
import math

from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QAbstractItemView, QFileDialog, QMessageBox
from PyQt5.QtCore import Qt, pyqtSlot, QItemSelectionModel, QModelIndex
from PyQt5.QtGui import QStandardItemModel, QStandardItem, QPainter, QPen, QColor, QBrush, QFont
from PyQt5.QtChart import QChart, QLineSeries, QValueAxis, QScatterSeries, QSplineSeries
from ui_MainWindow import Ui_MainWindow
from core import DataProcessing
from core import predictionParameters


class REDMainWindow(QMainWindow):
    tList = []
    QoList = []
    QwList = []
    NpList = []
    WpList = []
    LpList = []
    FwList = []
    dataRemake = [[], tList, QoList, QwList, NpList, WpList, LpList, FwList]

    def __init__(self, parent=None):
        super().__init__(parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.setWindowTitle("曲线预测")

        self.res = None  # 计算结果
        self.ui.tabWidget.setCurrentIndex(0)
        self.ui.lineEdit_14.setText("2")
        self.ui.lineEdit_15.setText("7")
        self.ui.label_well.setText("")
        self.ui.label_ii.setText("")

        # 建立表格区域
        self.__colCount = 8
        self.__rowCount = 30
        self.itemModel = QStandardItemModel(self.__rowCount, self.__colCount, self)
        self.selectModel = QItemSelectionModel(self.itemModel)
        self.selectModel.currentChanged.connect(self.do_curChanged)

        self.ui.tableView.setModel(self.itemModel)  # 设置数据模型
        self.ui.tableView.setSelectionModel(self.selectModel)  # 设置选择模型

        self.ui.tableView.setEnabled(False)
        # self.ui.tableView.setEditTriggers(QAbstractItemView.NoEditTriggers)

        # 建立图表区域
        self.__chart = None  # 图表
        self.__curSeries = None  # 当前序列
        self.__curAxis = None  # 当前坐标轴

        self.__createChartOfWeibull()
        self.__createChartOfIIWD()
        self.__createChartOfQoT()
        self.__createChartOfNpT()
        self.__createChartOfFwT()

        # 建立状态栏
        self.__buildStatusBar()

    ##  ==============自定义功能函数============
    def __buildStatusBar(self):
        """初始化状态栏"""
        self.LabCellPos = QLabel("当前单元格：", self)
        self.LabCellPos.setMinimumWidth(180)
        self.ui.statusbar.addWidget(self.LabCellPos)

        self.LabCellText = QLabel("单元格内容：", self)
        self.LabCellText.setMinimumWidth(150)
        self.ui.statusbar.addWidget(self.LabCellText)

        self.LabCurFile = QLabel("当前文件：", self)
        self.ui.statusbar.addPermanentWidget(self.LabCurFile)

    def __iniModelFromStringList(self, allLines):
        """从已经读取的字符串列表初始化表格"""
        rowCnt = len(allLines)
        self.itemModel.setRowCount(rowCnt - 1)

        headerText = allLines[0].strip()
        headerList = headerText.split("\t")
        self.itemModel.setHorizontalHeaderLabels(headerList)

        for i in range(rowCnt - 1):
            lineText = allLines[i + 1].strip()
            strList = lineText.split("\t")
            for j in range(self.__colCount):
                item = QStandardItem(strList[j])
                self.itemModel.setItem(i, j, item)  # 设置模型的item
        # self.dataRemake[j].append(float(strList[j])) #将每个cell放在其对应的cell

        for k in range(self.__colCount):
            self.ui.tableView.setColumnWidth(k, 90)

    def __createChartOfWeibull(self):
        self.__chart = QChart()
        self.__chart.setTitle("weibull曲线")
        self.ui.weibullChartView.setChart(self.__chart)
        self.ui.weibullChartView.setRenderHint(QPainter.Antialiasing)
        series0 = QScatterSeries()
        series0.setName("数据点")
        series1 = QLineSeries()
        series1.setName("趋势线")

        pen = QPen(Qt.red)
        pen.setStyle(Qt.DotLine)  # SolidLine, DashLine, DotLine, DashDotLine
        pen.setWidth(2)
        series0.setMarkerSize(3)
        series0.setPen(pen)  # 序列的线条设置

        pen.setStyle(Qt.SolidLine)  # SolidLine, DashLine, DotLine, DashDotLine
        pen.setColor(Qt.blue)
        series1.setPen(pen)  # 序列的线条设置

        self.__chart.addSeries(series0)
        self.__chart.addSeries(series1)

        axisX = QValueAxis()
        self.__curAxis = axisX  # 当前坐标轴
        axisX.setRange(0, 600)
        axisX.setLabelFormat("%.1f")
        axisX.setTickCount(11)
        axisX.setMinorTickCount(5)
        axisX.setTitleText("t^(b+1)")
        axisX.setGridLineVisible(True)
        axisX.setMinorGridLineVisible(False)

        axisY = QValueAxis()
        axisY.setRange(0, 2)
        axisY.setLabelFormat("%.2f")
        axisY.setTickCount(11)
        axisY.setMinorTickCount(5)
        axisY.setTitleText("lg(Qo/t^b)")
        axisY.setGridLineVisible(True)
        axisY.setMinorGridLineVisible(False)

        self.__chart.addAxis(axisX, Qt.AlignBottom)  # 坐标轴添加到图表，并指定方向
        self.__chart.addAxis(axisY, Qt.AlignLeft)

        series0.attachAxis(axisX)
        series0.attachAxis(axisY)

        series1.attachAxis(axisX)
        series1.attachAxis(axisY)

    def __createChartOfIIWD(self):
        self.__chart = QChart()
        self.__chart.setTitle("乙型水驱规律曲线")
        self.ui.iiWDChartView.setChart(self.__chart)
        self.ui.iiWDChartView.setRenderHint(QPainter.Antialiasing)
        series0 = QScatterSeries()
        series0.setName("数据点")
        series1 = QLineSeries()
        series1.setName("趋势线")

        pen = QPen(Qt.red)
        pen.setStyle(Qt.DotLine)  # SolidLine, DashLine, DotLine, DashDotLine
        pen.setWidth(2)
        series0.setMarkerSize(3)
        series0.setPen(pen)  # 序列的线条设置

        pen.setStyle(Qt.SolidLine)  # SolidLine, DashLine, DotLine, DashDotLine
        pen.setColor(Qt.blue)
        series1.setPen(pen)  # 序列的线条设置

        self.__chart.addSeries(series0)
        self.__chart.addSeries(series1)

        axisX = QValueAxis()
        self.__curAxis = axisX  # 当前坐标轴
        axisX.setRange(0, 3000)
        axisX.setLabelFormat("%d")
        axisX.setTickCount(11)
        axisX.setMinorTickCount(5)
        axisX.setTitleText("Np,(10^4t)")  # 标题
        axisX.setGridLineVisible(True)
        axisX.setMinorGridLineVisible(False)

        axisY = QValueAxis()
        axisY.setRange(0, 4.5)
        axisY.setLabelFormat("%.2f")
        axisY.setTickCount(11)
        axisY.setMinorTickCount(5)
        axisY.setTitleText("lgLp,(10^4t)")
        axisY.setGridLineVisible(True)
        axisY.setMinorGridLineVisible(False)

        self.__chart.addAxis(axisX, Qt.AlignBottom)  # 坐标轴添加到图表，并指定方向
        self.__chart.addAxis(axisY, Qt.AlignLeft)

        series0.attachAxis(axisX)
        series0.attachAxis(axisY)

        series1.attachAxis(axisX)
        series1.attachAxis(axisY)

    def __createChartOfQoT(self):
        self.__chart = QChart()
        self.__chart.setTitle("Qo-t曲线")
        self.ui.Qo_tChartView.setChart(self.__chart)
        self.ui.Qo_tChartView.setRenderHint(QPainter.Antialiasing)
        series0 = QScatterSeries()
        series0.setName("数据点")
        series1 = QSplineSeries()
        series1.setName("趋势线")

        pen = QPen(Qt.red)
        pen.setStyle(Qt.DotLine)  # SolidLine, DashLine, DotLine, DashDotLine
        pen.setWidth(2)
        series0.setMarkerSize(3)
        series0.setPen(pen)  # 序列的线条设置

        pen.setStyle(Qt.SolidLine)  # SolidLine, DashLine, DotLine, DashDotLine
        pen.setColor(Qt.blue)
        series1.setPen(pen)  # 序列的线条设置

        self.__chart.addSeries(series0)
        self.__chart.addSeries(series1)

        axisX = QValueAxis()
        self.__curAxis = axisX  # 当前坐标轴
        axisX.setRange(0, 40)
        axisX.setLabelFormat("%d")
        axisX.setTickCount(5)
        axisX.setMinorTickCount(5)
        axisX.setTitleText("t,(a)")  # 标题
        axisX.setGridLineVisible(True)
        axisX.setMinorGridLineVisible(False)

        axisY = QValueAxis()
        axisY.setRange(0, 200)
        axisY.setLabelFormat("%.2f")
        axisY.setTickCount(11)
        axisY.setMinorTickCount(5)
        axisY.setTitleText("Qo,(10^4t/a)")
        axisY.setGridLineVisible(True)
        axisY.setMinorGridLineVisible(False)

        self.__chart.addAxis(axisX, Qt.AlignBottom)  # 坐标轴添加到图表，并指定方向
        self.__chart.addAxis(axisY, Qt.AlignLeft)

        series0.attachAxis(axisX)
        series0.attachAxis(axisY)

        series1.attachAxis(axisX)
        series1.attachAxis(axisY)

    def __createChartOfNpT(self):
        self.__chart = QChart()
        self.__chart.setTitle("Np-t曲线")
        self.ui.Np_tChartView.setChart(self.__chart)
        self.ui.Np_tChartView.setRenderHint(QPainter.Antialiasing)
        series0 = QScatterSeries()
        series0.setName("数据点")
        series1 = QSplineSeries()
        series1.setName("趋势线")

        pen = QPen(Qt.red)
        pen.setStyle(Qt.DotLine)  # SolidLine, DashLine, DotLine, DashDotLine
        pen.setWidth(2)
        series0.setMarkerSize(3)
        series0.setPen(pen)  # 序列的线条设置

        pen.setStyle(Qt.SolidLine)  # SolidLine, DashLine, DotLine, DashDotLine
        pen.setColor(Qt.blue)
        series1.setPen(pen)  # 序列的线条设置

        self.__chart.addSeries(series0)
        self.__chart.addSeries(series1)

        axisX = QValueAxis()
        self.__curAxis = axisX  # 当前坐标轴
        axisX.setRange(0, 40)
        axisX.setLabelFormat("%d")
        axisX.setTickCount(5)
        axisX.setMinorTickCount(5)
        axisX.setTitleText("t,(a)")  # 标题
        axisX.setGridLineVisible(True)
        axisX.setMinorGridLineVisible(False)

        axisY = QValueAxis()
        axisY.setRange(0, 4000)
        axisY.setLabelFormat("%.2f")
        axisY.setTickCount(11)
        axisY.setMinorTickCount(5)
        axisY.setTitleText("Np,(10^4t)")
        axisY.setGridLineVisible(True)
        axisY.setMinorGridLineVisible(False)

        self.__chart.addAxis(axisX, Qt.AlignBottom)  # 坐标轴添加到图表，并指定方向
        self.__chart.addAxis(axisY, Qt.AlignLeft)

        series0.attachAxis(axisX)
        series0.attachAxis(axisY)

        series1.attachAxis(axisX)
        series1.attachAxis(axisY)

    def __createChartOfFwT(self):
        self.__chart = QChart()
        self.__chart.setTitle("Fw-t曲线")
        self.ui.Fw_tChartView.setChart(self.__chart)
        self.ui.Fw_tChartView.setRenderHint(QPainter.Antialiasing)
        series0 = QScatterSeries()
        series0.setName("数据点")
        series1 = QSplineSeries()
        series1.setName("趋势线")

        pen = QPen(Qt.red)
        pen.setStyle(Qt.DotLine)  # SolidLine, DashLine, DotLine, DashDotLine
        pen.setWidth(2)
        series0.setMarkerSize(3)
        series0.setPen(pen)  # 序列的线条设置

        pen.setStyle(Qt.SolidLine)  # SolidLine, DashLine, DotLine, DashDotLine
        pen.setColor(Qt.blue)
        series1.setPen(pen)  # 序列的线条设置

        self.__chart.addSeries(series0)
        self.__chart.addSeries(series1)

        axisX = QValueAxis()
        self.__curAxis = axisX  # 当前坐标轴
        axisX.setRange(0, 40)
        axisX.setLabelFormat("%d")
        axisX.setTickCount(5)
        axisX.setMinorTickCount(5)
        axisX.setTitleText("t,(a)")  # 标题
        axisX.setGridLineVisible(True)
        axisX.setMinorGridLineVisible(False)

        axisY = QValueAxis()
        axisY.setRange(0, 100)
        axisY.setLabelFormat("%.2f")
        axisY.setTickCount(11)
        axisY.setMinorTickCount(5)
        axisY.setTitleText("fw,(%)")
        axisY.setGridLineVisible(True)
        axisY.setMinorGridLineVisible(False)

        self.__chart.addAxis(axisX, Qt.AlignBottom)  # 坐标轴添加到图表，并指定方向
        self.__chart.addAxis(axisY, Qt.AlignLeft)

        series0.attachAxis(axisX)
        series0.attachAxis(axisY)

        series1.attachAxis(axisX)
        series1.attachAxis(axisY)

    def __prepareData(self):
        """建立5个曲线"""
        _, A, B, ABR2, alpha, beta, r2, a, b_fix, c, Fwmax, Qmax, tm, Nr = self.res

        # weibull======================================
        chart = self.ui.weibullChartView.chart()  # 获取QChartView中的QChart对象
        series0 = chart.series()[0]
        series0.clear()

        series1 = chart.series()[1]
        series1.clear()

        for i in range(len(self.dataRemake[2])):
            series0.append(self.dataRemake[1][i] ** (self.res[8] + 1),
                           math.log10(self.dataRemake[2][i] / (self.dataRemake[1][i]) ** self.res[8]))
        intv = 6
        x = 0
        for j in range(100):
            y = alpha + beta * x
            series1.append(x, y)
            x += intv

        # iiWD======================================
        chart = self.ui.iiWDChartView.chart()  # 获取chartView中的QChart对象
        series2 = chart.series()[0]
        series2.clear()

        series3 = chart.series()[1]
        series3.clear()

        for i in range(len(self.dataRemake[4])):
            series2.append(self.dataRemake[4][i], math.log10(self.dataRemake[6][i]))
        intv = 10
        x = 0
        for j in range(300):
            y = 10 ** (A + B * x)
            series3.append(x, math.log10(y))
            x += intv

        # Qo-t======================================
        chart = self.ui.Qo_tChartView.chart()  # 获取chartView中的QChart对象
        series4 = chart.series()[0]
        series4.clear()

        series5 = chart.series()[1]
        series5.clear()

        for i in range(len(self.dataRemake[1])):
            series4.append(self.dataRemake[1][i], self.dataRemake[2][i])
        intv = 1
        x = 0
        for j in range(40):
            y = a * x * math.exp(-(x ** (b_fix + 1) / c))
            series5.append(x, y)
            x += intv

        # Np-t======================================
        chart = self.ui.Np_tChartView.chart()  # 获取chartView中的QChart对象
        series6 = chart.series()[0]
        series6.clear()

        series7 = chart.series()[1]
        series7.clear()

        for i in range(len(self.dataRemake[1])):
            series6.append(self.dataRemake[1][i], self.dataRemake[4][i])
        intv = 1
        x = 0
        for j in range(40):
            y = a * c / (b_fix + 1) * (1 - math.exp(-(x ** (b_fix + 1)) / c))
            series7.append(x, y)
            x += intv

        # Fw-t======================================
        chart = self.ui.Fw_tChartView.chart()  # 获取chartView中的QChart对象
        series8 = chart.series()[0]
        series8.clear()

        series9 = chart.series()[1]
        series9.clear()

        for i in range(len(self.dataRemake[1])):
            series8.append(self.dataRemake[1][i], self.dataRemake[7][i])
        intv = 1
        x = 0
        for j in range(40):
            y = 1 - math.pow(10, -(
                    A + B * (a * c / (b_fix + 1) * (1 - math.exp(-(x ** (b_fix + 1)) / c))) + math.log10(2.303 * B)))
            if y < 0:
                series9.append(x, 0)
            else:
                series9.append(x, y * 100)
            x += intv

    def __showData(self, t_start=1, Lp_start=6):
        """展示计算结果"""
        self.res = DataProcessing(self.tList, self.QoList, self.NpList, self.LpList, t_start, Lp_start)
        _, A, B, ABR2, alpha, beta, r2, a, b_fix, c, Fwmax, Qmax, tm, Nr = self.res
        predictionParameters(50, a, b_fix, c, A, B)
        self.ui.lineEdit.setText(self.res[1].__str__())
        self.ui.lineEdit_2.setText(self.res[2].__str__())
        self.ui.lineEdit_3.setText(self.res[3].__str__())
        self.ui.lineEdit_4.setText(self.res[4].__str__())
        self.ui.lineEdit_5.setText(self.res[5].__str__())
        self.ui.lineEdit_6.setText(self.res[6].__str__())
        self.ui.lineEdit_7.setText(self.res[7].__str__())
        self.ui.lineEdit_8.setText(self.res[8].__str__())
        self.ui.lineEdit_9.setText(self.res[9].__str__())
        self.ui.lineEdit_10.setText((self.res[10] * 100).__str__())
        self.ui.lineEdit_11.setText(self.res[11].__str__())
        self.ui.lineEdit_12.setText(self.res[12].__str__())
        self.ui.lineEdit_13.setText(self.res[13].__str__())
        self.__prepareData()
        self.__updateLable()

    def __updateLable(self):
        """更新预测函数标签"""
        _, A, B, ABR2, alpha, beta, r2, a, b_fix, c, Fwmax, Qmax, tm, Nr = self.res
        self.ui.label_well.setText("y=" + str(beta) + "x+" + str(alpha) + " r^2=" + str(r2))
        self.ui.label_ii.setText("y=" + str(B) + "x+" + str(A) + " r^2=" + str(ABR2))

    ##  ==============自动连接槽函数============
    @pyqtSlot()
    def on_readData_triggered(self):
        """文件读取槽函数"""
        curPath = os.getcwd()  # 获取当前路径

        filename, flt = QFileDialog.getOpenFileName(self, "打开一个文件", curPath,
                                                    "ANSI文本文档(*.txt);;所有文件(*.*)")
        if (filename == ""):
            return

        self.LabCurFile.setText("当前文件：" + filename)

        aFile = open(filename, 'r')
        allLines = aFile.readlines()  # 读取所有行,list类型,每行末尾带有 \n
        aFile.close()

        self.__iniModelFromStringList(allLines)
        self.ui.tableView.setEnabled(True)

    @pyqtSlot()
    def on_pushButton_enter_clicked(self):
        """数据处理槽函数"""
        for k in range(self.itemModel.columnCount()):
            self.dataRemake[k].clear()
        try:
            for i in range(self.itemModel.rowCount()):
                for j in range(self.itemModel.columnCount()):
                    item = self.itemModel.item(i, j)
                    self.dataRemake[j].append(float(item.text()))
        except:
            QMessageBox.critical(self, "类型错误", "数据类型有错误，请检查")
        else:
            self.__showData()

    @pyqtSlot()
    def on_lineEdit_14_editingFinished(self):
        """weibull曲线从某点开始的槽函数"""
        self.__showData(t_start=int(self.ui.lineEdit_14.text()) - 1, Lp_start=int(self.ui.lineEdit_15.text()) - 1)

    @pyqtSlot()
    def on_lineEdit_15_editingFinished(self):
        """乙型水驱曲线从某点开始的槽函数"""
        self.__showData(t_start=int(self.ui.lineEdit_14.text()) - 1, Lp_start=int(self.ui.lineEdit_15.text()) - 1)

    ##  =============自定义槽函数===============================
    def do_curChanged(self, current, previous):
        """cell变化时状态栏的槽函数"""
        if (current != None):  # 当前模型索引有效
            text = "当前单元格：%d行，%d列" % (current.row(), current.column())
            self.LabCellPos.setText(text)
            item = self.itemModel.itemFromIndex(current)  # 从模型索引获得Item
            self.LabCellText.setText("单元格内容：" + item.text())  # 显示item的文字内容


##  ============窗体测试程序 ================================
if __name__ == "__main__":
    """主程序入口"""
    app = QApplication(sys.argv)
    form = REDMainWindow()
    form.show()
    sys.exit(app.exec_())
